using System;
using DOJ.LEISP.LEXS.Common.Providers;
using System.Collections.Generic;

namespace DOJ.LEISP.LEXS.Services.SearchRetrieve
{

    /// <summary>
    /// Implementation of the LEXS Search Retrieve Port Type
    /// </summary>
    [System.ServiceModel.ServiceBehaviorAttribute(InstanceContextMode = System.ServiceModel.InstanceContextMode.PerCall)]
    public class LEXSSearchRetrievePortType : ILEXSSearchRetrievePortType
    {

        ISRMessageMetadataProvider _metaDataProvider;
        IStructuredSearchProvider _structuredSearchProvider;
        IDomainProvider _domainProvider;
        IAvailabilityProvider _availabilityProvider;
        IDataOwnerProvider _dataOwnerProvider;
        ITextSearchProvider _textSearchProvider;
        ICapabilitiesProvider _capabilitiesProvider;

        /// <summary>
        /// Initializes a new instance of the LEXSSearchRetrievePortType class.
        /// </summary>
        public LEXSSearchRetrievePortType()
        {
            _metaDataProvider = new DefaultMetadataProvider();
            _structuredSearchProvider = new DefaultSructuredSearchProvider();
            _domainProvider = new DefaultDomainProvider();
            _availabilityProvider = new DefaultAvailabilityProvider();
            _dataOwnerProvider = new DefaultDataOwnerProvider();
            _textSearchProvider = new DefaultTextSearchProvider();
            _capabilitiesProvider = new DefaultCapabilitiesProvider();
        }

        public virtual doStructuredSearchResponse doStructuredSearch(doStructuredSearchRequest request)
        {
            ResultCodeSimpleType resultCode;
            SearchResponseMetadataType searchResponseMeta;
            SRMessageMetadataType metaData = _metaDataProvider.GetMetaData(request.StructuredSearchRequestMessage.SRMessageMetadata);
            List<DataCategoryCodeType> dataCategories = new List<DataCategoryCodeType>();
            Array.ForEach(request.StructuredSearchRequestMessage.SearchRequestMetadata.RequestedData, item => dataCategories.Add(item));
            List<SearchResultPackageType> results = _structuredSearchProvider.DoStructuredSearch(new List<StructuredQueryType>(request.StructuredSearchRequestMessage.StructuredQuery), Int32.Parse(request.StructuredSearchRequestMessage.SearchRequestMetadata.MaxItemMatches.Value), dataCategories, out resultCode, out searchResponseMeta);

            doStructuredSearchResponse response = new doStructuredSearchResponse { SearchResponseMessage = new SearchResponseMessageType() };
            response.SearchResponseMessage.SRMessageMetadata = metaData;
            response.SearchResponseMessage.ResponseMetadata = new ResponseMetadataType();
            response.SearchResponseMessage.ResponseMetadata.ResultCode = new ResultCodeType { Value = resultCode };
            response.SearchResponseMessage.ResponseMetadata.InResponseToMessageSequenceNumber = request.StructuredSearchRequestMessage.SRMessageMetadata.MessageSequenceNumber;
            response.SearchResponseMessage.SearchResultPackage = results.ToArray();
            response.SearchResponseMessage.SearchResponseMetadata = searchResponseMeta;

            return response;
        }

        public virtual doStructuredSearchResponse doTextSearch(doTextSearchRequest request)
        {
            ResponseMetadataType responseMeta;
            SearchResponseMetadataType searchResponseMeta;
            SRMessageMetadataType metaData = _metaDataProvider.GetMetaData(request.TextSearchRequestMessage.SRMessageMetadata);
            List<SearchResultPackageType> results = _textSearchProvider.DoTextSearch(request.TextSearchRequestMessage.SearchRequestMetadata, request.TextSearchRequestMessage.TextQuery, out responseMeta, out searchResponseMeta);
            SearchResponseMessageType response = new SearchResponseMessageType();
            response.SRMessageMetadata = metaData;
            if (results != null) { response.SearchResultPackage = results.ToArray(); }
            response.ResponseMetadata = responseMeta;
            response.SearchResponseMetadata = searchResponseMeta;
            response.ResponseMetadata.InResponseToMessageSequenceNumber = request.TextSearchRequestMessage.SRMessageMetadata.MessageSequenceNumber;

            return new doStructuredSearchResponse(response);
        }

        public virtual getDataItemResponse getDataItem(getDataItemRequest request)
        {
            throw new System.NotImplementedException();
        }

        public virtual getAttachmentResponse getAttachment(getAttachmentRequest request)
        {
            throw new System.NotImplementedException();
        }

        public virtual getCapabilitiesResponse getCapabilities(getCapabilitiesRequest request)
        {
            CapabilitiesResponseMessageType response = new CapabilitiesResponseMessageType() 
            { 
                SRMessageMetadata = _metaDataProvider.GetMetaData(request.ServiceProviderRequestMessage.SRMessageMetadata), 
                Capabilities = _capabilitiesProvider.GetCapabilities(),
                ResponseMetadata = new ResponseMetadataType()
                {
                     ResultCode = new ResultCodeType {Value = ResultCodeSimpleType.Success},
                     InResponseToMessageSequenceNumber = request.ServiceProviderRequestMessage.SRMessageMetadata.MessageSequenceNumber
                     
                }
            };
            return new getCapabilitiesResponse(response);
        }

        public virtual getDataOwnersResponse getDataOwners(getDataOwnersRequest request)
        {
            DataOwnersResponseMessageType response = new DataOwnersResponseMessageType
            {
                SRMessageMetadata = _metaDataProvider.GetMetaData(request.ServiceProviderRequestMessage.SRMessageMetadata),
                DataOwnerInformation = _dataOwnerProvider.GetDataOwners().ToArray(),
                ResponseMetadata = new ResponseMetadataType()
            };
            response.ResponseMetadata.InResponseToMessageSequenceNumber = request.ServiceProviderRequestMessage.SRMessageMetadata.MessageSequenceNumber;
            response.ResponseMetadata.ResultCode = new ResultCodeType { Value = ResultCodeSimpleType.Success };

            return new getDataOwnersResponse(response);
        }

        public virtual getAvailabilityResponse getAvailability(getAvailabilityRequest request)
        {
            AvailabilityResponseMessageType response = new AvailabilityResponseMessageType
            {
                SRMessageMetadata = _metaDataProvider.GetMetaData(request.ServiceProviderRequestMessage.SRMessageMetadata),
                ServiceAvailableIndicator = _availabilityProvider.GetAvailabliity(),
                ResponseMetadata = new ResponseMetadataType()
            };
            response.ResponseMetadata.ResultCode = new ResultCodeType { Value = ResultCodeSimpleType.Success };
            response.ResponseMetadata.InResponseToMessageSequenceNumber = request.ServiceProviderRequestMessage.SRMessageMetadata.MessageSequenceNumber;

            return new getAvailabilityResponse(response);
        }

        public virtual getDomainResponse getDomain(getDomainRequest request)
        {
            DomainResponseMessageType response = new DomainResponseMessageType();
            SRMessageMetadataType metaData = _metaDataProvider.GetMetaData(request.DomainRequestMessage.SRMessageMetadata);
            response.DomainAttribute = _domainProvider.GetDomains().ToArray();
            response.SRMessageMetadata = metaData;
            response.ResponseMetadata = new ResponseMetadataType();
            response.ResponseMetadata.ResultCode = new ResultCodeType { Value = ResultCodeSimpleType.Success };
            response.ResponseMetadata.InResponseToMessageSequenceNumber = request.DomainRequestMessage.SRMessageMetadata.MessageSequenceNumber;

            return new getDomainResponse(response);
        }
    }
}
